// PFMImage.cpp
//

#include "PFMImage.h"
#include "loadPNM.h"

using namespace std;

#define DEBUG

#ifdef DEBUG 
#define DPRINTF(fmt, ...) \
    do { printf(__FILE__": " fmt, ## __VA_ARGS__); } while (0)
#else
#define DPRINTF(fmt, ...) \
    do { } while (0)
#endif

PFMImage::PFMImage(unsigned int width, unsigned int height,
        unsigned int num_components) :
		width(width), height(height), num_components(num_components)
{
	imageData = new float[width * height * num_components];
	filename = "<unsaved>";
	exposure = -1;

	////
	DPRINTF( "Created new empty image width:%d height:%d num_components:%d\n",
	        width, height, num_components);
	////
}

PFMImage::PFMImage(string filename) :
		filename(filename)
{
	imageData = loadPFM(filename.c_str(), width, height, num_components);
	exposure = -1;

	////
	DPRINTF("Loaded %s width:%d height:%d num_components:%d\n",
	        filename.c_str(), width, height, num_components);
	////
}

PFMImage::~PFMImage()
{
	delete[] imageData;

	////
	DPRINTF("Unloading %s from memory\n", filename.c_str());
	////
}

void PFMImage::write(string filename)
{
	this->filename = filename;
	WritePFM(filename.c_str(), width, height, num_components, imageData);

	////
	DPRINTF("Saved PFM file %s width:%d height:%d num_components:%d\n",
	        filename.c_str(), width, height, num_components);
	////
}

// Convert the 0-1.0 float buffer to a 0-255 buffer and pass to WritePNM
void PFMImage::writePPM(string filename)
{
	this->filename = filename;

	// Just an alias
	float *img_in = imageData;

	// Code below copied from sample
	// **********
	unsigned char *img_out = new unsigned char [width*height*num_components];

	for (uint i = 0; i < height; ++i) // height
	{
		for (uint j = 0; j < width; ++j) // width
		{
			// color channels - 3 for RGB images
			for (uint k = 0; k < num_components; ++k)
			{
				//index within the image
				uint index =
						i * width * num_components + j * num_components + k;

				//typecast 0.0f -> 1.0f values to the 0 - 255 range

				// R
				img_out[index] =
						static_cast<unsigned char>(img_in[index] * 255.0f);

				// G
				img_out[index + 1] =
				        static_cast<unsigned char>(img_in[index + 1] * 255.0f);

				// B
				img_out[index + 2] =
				        static_cast<unsigned char>(img_in[index + 2] * 255.0f);

			}

		}
	}
	// **********

	////
	DPRINTF("Saved PNM file %s width:%d height:%d num_components:%d\n",
	        filename.c_str(), width, height, num_components);
	////

	WritePNM(filename.c_str(), width, height, num_components, img_out);

	// Free the output buffer
	delete[] img_out;
}

float * PFMImage::getData()
{
	return imageData;
}

unsigned int PFMImage::getWidth()
{
	return this->width;
}

unsigned int PFMImage::getHeight()
{
	return this->height;
}

unsigned int PFMImage::getNumComponents()
{
	return this->num_components;
}

void PFMImage::setExposure(unsigned int exp)
{
	this->exposure = exp;
}

unsigned int PFMImage::getExposure()
{
	return this->exposure;
}
